package com.ruoyi.system.coretools.pay;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.http.OkHttpUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.system.domain.TPayHistory;
import com.ruoyi.system.domain.TUserInfo;
import com.ruoyi.system.mapper.TPayHistoryMapper;
import com.ruoyi.system.mapper.TUserInfoMapper;
import com.ruoyi.system.service.ISysConfigService;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

@Component
public class PayUtilsV2 {
    @Autowired
    TPayHistoryMapper tPayHistoryMapper;
    @Autowired
    TUserInfoMapper tUserInfoMapper;
    private static final Logger log = LoggerFactory.getLogger(PayUtilsV2.class);
    //payUrl后面做成配置
    public static String agentId = "";//merchantId
    //支付地址前缀
    public static String payUrl = "";
    //回调地址url
    public static String callbackUrl = "";
    public static String tixianCallbackUrl = "";

    public static String payUrlSuccess = "";//pay_url_success//支付成功回跳地址
    public static String payUrlReturn = "";//pay_url_return//支付前回调地址

    //apiKey
    public static String apiKey = "";
    public static String apiKeyTx = "";


    public PayUtilsV2() {
        ISysConfigService configService = SpringUtils.getBean(ISysConfigService.class);
        agentId = configService.selectConfigByKey("pay.config.agentId");//merchantId
        payUrl = configService.selectConfigByKey("pay.config.payUrl");
        callbackUrl = configService.selectConfigByKey("pay.config.callbackUrl");
        tixianCallbackUrl = configService.selectConfigByKey("pay.config.tixianCallbackUrl");

        payUrlSuccess = configService.selectConfigByKey("pay.config.pay_url_success"); //支付成功回跳地址
        payUrlReturn =  configService.selectConfigByKey("pay.config.pay_url_return");//支付前回调地址



        apiKey = configService.selectConfigByKey("pay.config.apiKey");
        apiKeyTx = configService.selectConfigByKey("pay.config.apiKeyTx");
    }


    /**
     * 充值
     * curl https://api.cryptomus.com/v1/payment \-X POST \-H 'merchant: 8b03432e-385b-4670-8d06-064591096795' \-H 'sign: fe99035f86fa436181717b302b95bacff1' \-H 'Content-Type: application/json' \-d '{	"amount": "15",	"currency": "USD",	"order_id": "1",}'
     * {	"state": 0,	"result": {		"uuid": "26109ba0-b05b-4ee0-93d1-fd62c822ce95",		"order_id": "1",		"amount": "15.00",		"payment_amount": null,		"payer_amount": null,		"discount_percent": null,		"discount": "0.00000000",		"payer_currency": null,		"currency": "USD",		"merchant_amount": null,		"network": null,		"address": null,		"from": null,		"txid": null,		"payment_status": "check",		"url": "https://pay.cryptomus.com/pay/26109ba0-b05b-4ee0-93d1-fd62c822ce95",		"expired_at": 1689098133,		"status": "check",		"is_final": false,		"additional_data": null,		"created_at": "2023-07-11T20:23:52+03:00",		"updated_at": "2023-07-11T21:24:17+03:00"	}}
     */
    @Transactional
    public String createChongzhiOrder(long userId, float amount) throws Exception {


        log.info("收到发起收款原始请求:userId:{} orderId:{} amount:{}", userId, amount);
        //10位时间戳
        int time = (int) (System.currentTimeMillis() / 1000);

        JSONObject param = new JSONObject();
        //param.put("agent_id", agentId);
        //param.put("user_id", userId);
        String orderId = UUID.randomUUID().toString();
        param.put("order_id", orderId);
        param.put("amount", amount + "");
        param.put("currency", "TRX");//USD
        param.put("url_callback", callbackUrl);
        param.put("to_currency","TRX");//用TRX币付款
        param.put("url_success",payUrlSuccess);
        param.put("url_return",payUrlReturn);
        //param.put("time", time);
        //构建签名

        String sign = getCryptomusSign(JSONObject.toJSONString(param), apiKey);
        //String sign = DigestUtils.md5Hex(JSONObject.toJSONString(param) + apiKey);
        //log.info("MD5 Hash:{}", md5Hash);
        //param.put("sign", md5Hash);


        //入库记录，用于回调变更确认。
        TPayHistory tPayHistory = new TPayHistory();
        tPayHistory.setAgentId(agentId);
        tPayHistory.settUserId(userId);
        tPayHistory.setOrderId(orderId);
        tPayHistory.setAmount(new BigDecimal(amount));
        tPayHistory.setUrl(callbackUrl);
        tPayHistory.setTime(time);
        tPayHistory.setOperationType(1);
        tPayHistory.setOperationStatus(0);
        tPayHistory.setOperationDescription("充值");
        tPayHistory.setUserId(userId + "");
        tPayHistoryMapper.insertTPayHistory(tPayHistory);


        //用户表金额加上
        TUserInfo tUserInfo = tUserInfoMapper.selectTUserInfoById(tPayHistory.gettUserId());
        //减去更新金额
        tUserInfo.setMoney(tUserInfo.getMoney() == null ? new BigDecimal(amount) : tUserInfo.getMoney().add(tPayHistory.getAmount()));
        //更新金额
        tUserInfoMapper.updateById(tUserInfo);

        try {
            log.info("充值报文:{}",param.toJSONString());
            //在此处编写要执行的任务代码
            String result = OkHttpUtils.builder().url(payUrl + "/v1/payment")
                    .addHeader("Content-Type", "application/json; charset=utf-8")
                    .addHeader("sign", sign)
                    .addHeader("merchant", agentId)
                    .postJson(true, param.toJSONString())
                    .sync();
            log.info("支付接口返回的原始报文:{}", result);
            //支付接口返回的原始报文:{"state":0,"result":{"uuid":"0f91dc22-029e-4a45-8987-daa4a2d4d830","order_id":"7fc1db80-6720-4af1-9be0-c76a53d55a14","amount":"1.00","payment_amount":null,"payment_amount_usd":null,"payer_amount":null,"payer_amount_exchange_rate":null,"discount_percent":null,"discount":"0.00000000","payer_currency":null,"currency":"USD","comments":null,"merchant_amount":null,"network":null,"address":null,"from":null,"txid":null,"payment_status":"check","url":"https:\/\/pay.cryptomus.com\/pay\/0f91dc22-029e-4a45-8987-daa4a2d4d830","expired_at":1720439828,"status":"check","is_final":false,"additional_data":null,"created_at":"2024-07-08T13:57:08+03:00","updated_at":"2024-07-08T13:57:08+03:00","commission":null,"address_qr_code":null}}
            JSONObject jsonObject = JSON.parseObject(result);
            if (jsonObject.getIntValue("state") == 1 || jsonObject.getIntValue("state") == 0) {
                //获取收银台url
                String shouyintaiUrl = jsonObject.getJSONObject("result").getString("url");
                String status = jsonObject.getJSONObject("result").getString("status");
                if ("check".equals(status)) {
                    //拿到收款地址
                    log.info("支付接口返回的原始报文:{}", shouyintaiUrl);
                    return shouyintaiUrl;
                } else {
                    throw new ServiceException("三方充值接口调用失败,收银台地址不是指定步骤。", HttpStatus.ERROR);
                }


            }
        } catch (Exception e) {
            throw new ServiceException("三方充值接口调用失败", HttpStatus.ERROR);
        }


        return null;

    }


    /**
     * 提现
     * curl https://api.cryptomus.com/v1/payout \-X POST \-H 'merchant: 8b03432e-385b-4670-8d06-064591096795' \-H 'sign: fe99035f86fa436181717b302b95bacff1' \-H 'Content-Type: application/json' \-d '{     "amount": "5",    "currency": "USDT",     "network": "TRON",     "order_id": "1",    "address": "TDD97yguPESTpcrJMqU6h2ozZbibv4Vaqm",     "url_callback": "https://your.site/callback",     "is_subtract": "1",}'
     * {    "state": 0,    "result": {        "uuid": "a7c0caec-a594-4aaa-b1c4-77d511857594",         "amount": "3",        "currency": "USDT",        "network": "TRON",        "address": "TJ...",        "txid": null,        "status": "process",        "is_final": false,        "balance": 129,        "payer_currency": "USD",        "payer_amount": 3    }}
     */
    @Transactional
    public Boolean createTiXianOrder(long userId, float amount, String address_user) throws Exception {
        //tVvKftyTQL8vZthDBHtni1NoNqOSOV7D8aEotNmMndkiH9WL4jLdXylnSRkqoFQCU9HCif8oJwPXKvzEODOO7xGTzxprLoFENPahERNcHE1fUuTIqCkcsTiJCPVIVNFW
        //提现的时候真正到款要减去平台提现手续费
        ISysConfigService configService = SpringUtils.getBean(ISysConfigService.class);
        String embodyMoney = configService.selectConfigByKey("embodyMoney");
        String vipEmbodyMoney = configService.selectConfigByKey("vipEmbodyMoney");
        double shouxufei = 0;

        //检查vip适配手续费
        TUserInfo tUserInfo = tUserInfoMapper.selectTUserInfoById(userId);
        boolean isVip = tUserInfo.getVipId() != null && tUserInfo.getVipId().longValue() != 0 ? true : false;
        if (isVip) {
            shouxufei = amount * Double.parseDouble(vipEmbodyMoney);
        } else {
            shouxufei = amount * Double.parseDouble(embodyMoney);
        }


        log.info("收到发起提现原始请求:userId:{} issueId:{} amount:{} address_user:{}", userId, amount, address_user);
        //10位时间戳
        int time = (int) (System.currentTimeMillis() / 1000);

        Gson gson = new Gson();
        JsonObject param = new JsonObject();
        //param.put("user_id", userId);
        String orderId = UUID.randomUUID().toString();

        param.addProperty("amount", amount - shouxufei + "");//真正提现算了手续费的
        param.addProperty("currency", "TRX");
        param.addProperty("network", "TRON");
        param.addProperty("order_id", orderId);
        param.addProperty("address", address_user);
        param.addProperty("url_callback", tixianCallbackUrl);
        param.addProperty("is_subtract", 1);

        //构建签名
        /*$data = json_encode($data);
        $sign = md5(base64_encode($data) . $API_KEY);*/


        //String sign = DigestUtils.md5(Base64Encoder.encode(JSONObject.toJSONString(param)) + apiKey).toString();
        //System.out.println(sign);
        String sign = getCryptomusSign(gson.toJson(param), apiKeyTx);
        insertTiXianPayHistoryInfo(userId, amount, time, orderId, sign, address_user);


        try {
            log.info("提现报文:{}",gson.toJson(param));
            //在此处编写要执行的任务代码
            String result = OkHttpUtils.builder().url(payUrl + "/v1/payout")
                    .addHeader("merchant", agentId)
                    .addHeader("sign", sign)
                    .addHeader("Content-Type", "application/json; charset=utf-8")


                    .postJson(true, gson.toJson(param))
                    .sync();
            log.info("支付接口返回的原始报文:{}", result);
            JSONObject jsonObject = JSON.parseObject(result);
            if (jsonObject.getJSONObject("result").getString("status").equals("process")) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            throw new ServiceException("三方提现接口调用失败", HttpStatus.ERROR);
        }


    }


    public String getCryptomusSign(String jsonData, String key) {
        String jsonBase64 = Base64.getEncoder().encodeToString(jsonData.getBytes(StandardCharsets.UTF_8));
        return EncodeUtil.bytesToHex(
                EncodeUtil.digestMD5((jsonBase64 + key).getBytes(StandardCharsets.UTF_8))
        );
    }

    @Transactional
    public void insertTiXianPayHistoryInfo(long userId, float amount, int time, String issueId, String sign, String addressUser) throws Exception {

        //先校验余额够不够
        //多一个冻结金额动作
        TUserInfo tUserInfo = tUserInfoMapper.selectTUserInfoById(userId);

        if (tUserInfo.getMoney() == null || tUserInfo.getMoney().compareTo(new BigDecimal(amount)) == -1) {
            throw new ServiceException("提现失败,用户充值剩余的账户余额小于提现金额");
        }


        //入库
        TPayHistory tPayHistory = new TPayHistory();
        tPayHistory.setAgentId(agentId);
        tPayHistory.settUserId(userId);
        tPayHistory.setOrderId(issueId);
        tPayHistory.setAmount(new BigDecimal(amount));
        tPayHistory.setUrl(tixianCallbackUrl);
        tPayHistory.setTime(time);
        tPayHistory.setOperationType(2);
        tPayHistory.setOperationStatus(0);
        tPayHistory.setOperationDescription("提现");
        tPayHistory.setUserId(userId + "");
        tPayHistory.setSign(sign);
        tPayHistory.setAddressUser(addressUser);
        tPayHistoryMapper.insertTPayHistory(tPayHistory);


        //减去更新金额
        tUserInfo.setMoney(tUserInfo.getMoney().subtract(tPayHistory.getAmount()));
        //加上更新冻结金额
        tUserInfo.setFreezMoney(null!=tUserInfo.getFreezMoney()?tUserInfo.getFreezMoney().add(tPayHistory.getAmount()):tPayHistory.getAmount());//冻结金额+第二笔提现的冻结金额
        tUserInfoMapper.updateById(tUserInfo);
    }


    /**
     * 查询提现状态
     * /issue_info
     * ```
     * - 请求参数
     * - agent_id(代理id)(string)
     * - issue_id(下发订单id)(string)
     *
     * <p>
     * - 返回示例
     * -
     * ```
     * {
     * "state": 4,//1=等待审核,2=审核通过,3=正在下发,4=下发成功
     * "text": "下发成功",
     * "data": {
     * "id": 1,
     * "issue_id": "123",
     * "user_id": "123",
     * "agent_id": "123",
     * "time": 1712549570,
     * "amount": 123,//下发金额
     * "state":4,
     * "address_user":"TdeEf45...",//客户的地址,
     * "address_agent":"TEdfs2..."//下发的主地址
     * }
     * }
     * ```
     */
    public JSONObject queryTiXianOrderStatus(String issueId) {
        try {
            log.info("收到发起查提现状态原始请求:issueId:{} ", issueId);

            JSONObject param = new JSONObject();
            param.put("agent_id", agentId);
            param.put("issue_id", issueId);

            //调提现接口
            String result = OkHttpUtils.builder().url(payUrl + "/issue_info")
                    .addHeader("Content-Type", "application/json; charset=utf-8")
                    .postJson(true, param.toJSONString())
                    .sync();
            log.info("支付接口返回的原始报文:{}", result);
            JSONObject jsonObject = JSON.parseObject(result);
            if (jsonObject.getIntValue("state") == 1) {
                log.info("查询提现状态返回的原始报文:{}", jsonObject);
                return jsonObject;
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("查询提现失败", HttpStatus.ERROR);
        }
        return null;

    }


}
